package com.yky.utils;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yky.model.HotKeyModel;
import com.yky.service.HotKeyService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 业务聚合
 *
 * @version [V2.0]
 * @package com.example.utils;
 * @description:[用一句话描述该文件做什么]
 * @author: [zhuben]
 * @date: [2024-02-02 10:46]
 * @copyright: 2024 echovin.com
 */
@Component
public class HotKeyUtils {
    private static final Logger log = LoggerFactory.getLogger(HotKeyUtils.class);
    @Resource
    private RedisUtils redisUtils;
    @Resource
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
    @Resource
    private HotKeyService hotKeyService;
    private static final String FIREWALLD = "hotkeys:firewalld";


    public void save(List<HotKeyModel> hotKeyModels){
        if (hotKeyModels == null || hotKeyModels.size() <= 0){
            return;
        }

        threadPoolTaskExecutor.execute(()->{
            for (HotKeyModel hotKeyModel : hotKeyModels){
                try {
                    LambdaQueryWrapper<HotKeyModel> queryWrapper = new LambdaQueryWrapper<>();
                    queryWrapper.eq(HotKeyModel::getBusinessId, hotKeyModel.getBusinessId());
                    queryWrapper.eq(HotKeyModel::getHotKey, hotKeyModel.getHotKey());
                    HotKeyModel one = hotKeyService.getOne(queryWrapper);
                    if (one != null){
                        one.setBusinessType(hotKeyModel.getBusinessType());
                        one.setStaffId(hotKeyModel.getStaffId());
                        one.setDeptId(hotKeyModel.getDeptId());
                        one.setWardId(hotKeyModel.getWardId());
                        one.setHospitalId(hotKeyModel.getHospitalId());
                        hotKeyService.updateById(one);
                    }else{
                        hotKeyService.save(hotKeyModel);
                    }

                } catch (Exception e) {
                    log.error("保存更新热度DB数据失败，原因：", e);
                }
                try {
                    redisUtils.zIncrby(hotKeyModel.getHotKey(), hotKeyModel.getBusinessId(), 1);
                } catch (Exception e) {
                    log.error("保存更新热度缓存数据失败，原因：", e);
                }
            }
        });
    }

    public List<String> get(String businessType, String staffId, String deptId, String wardId, String hospitalId){
        List<String> hotKeys = new ArrayList<>();
        String key = this.buildHotKeyStr(businessType, staffId, deptId, wardId, hospitalId);
        try {
            List<String> result = redisUtils.zRevRangeWithScore(key, 0, 5);
            if (result != null && result.size() > 0){
                return result;
            }

            //防击穿
            String hit = redisUtils.get(FIREWALLD);
            if (StringUtils.isBlank(hit)){
                //查询db
                List<HotKeyModel> hotKeyModels = hotKeyService.selectListByHotKey(key, 1, 5);
                if (hotKeyModels != null && hotKeyModels.size() > 0){
                    hotKeys = hotKeyModels.stream().filter(s->StringUtils.isNotBlank(s.getBusinessId())).map(HotKeyModel::getBusinessId).collect(Collectors.toList());
                    hotKeyModels.forEach(s->{
                        redisUtils.zIncrby(key, s.getBusinessId(), s.getScore());
                    });
                }
                redisUtils.set(FIREWALLD, key, 10);
            }
        } catch (Exception e) {
            //异常查询db
            List<HotKeyModel> hotKeyModels = hotKeyService.selectListByHotKey(key, 1, 5);
            if (hotKeyModels != null && hotKeyModels.size() > 0){
                hotKeys = hotKeyModels.stream().filter(s->StringUtils.isNotBlank(s.getBusinessId())).map(HotKeyModel::getBusinessId).collect(Collectors.toList());
            }
        }
        return hotKeys;
    }


    public String buildHotKeyStr(String businessType, String staffId, String deptId, String wardId, String hospitalId){
        StringBuilder stringBuilder = new StringBuilder("hotkeys");
        if (StringUtils.isNotBlank(hospitalId)){
            stringBuilder.append(":").append(hospitalId);
        }
        if (StringUtils.isNotBlank(businessType)){
            stringBuilder.append(":").append(businessType);
        }
        if (StringUtils.isNotBlank(staffId)){
            stringBuilder.append(":").append(staffId);
        }
        if (StringUtils.isNotBlank(deptId)){
            stringBuilder.append(":").append(deptId);
        }
        if (StringUtils.isNotBlank(wardId)){
            stringBuilder.append(":").append(wardId);
        }
        return stringBuilder.toString();
    }
}
